package com.siro.auth.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.siro.auth.entity.SysMenu;
import com.siro.auth.entity.SysUser;
import com.siro.auth.entity.vo.RoleMenuVo;
import com.siro.auth.mapper.SysMenuMapper;
import com.siro.auth.mapper.SysUserMapper;
import com.siro.auth.service.ISysMenuService;
import com.siro.auth.base.common.domain.MenuTree;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @author GH
 * @description 针对表【sys_menu】的数据库操作Service实现
 * @createDate 2022-07-18 18:03:33
 */
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements ISysMenuService {

    @Autowired
    private SysUserMapper sysUserMapper;

    /**
     * 根据用户ID查询权限
     *
     * @param userId 用户ID
     * @return 权限列表
     */
    @Override
    public List<SysMenu> selectMenuPermsByUserId(Long userId) {
        // TODO 判断管理员 和 普通用户的权限
        List<SysMenu> sysMenuList = baseMapper.selectMenuPermsByUserId(userId);
        return sysMenuList;
    }

    /**
     * 查询菜单列表
     *
     * @param sysMenu
     * @return
     */
    @Override
    public List<SysMenu> getMenuList(SysMenu sysMenu) {
        QueryWrapper<SysMenu> queryWrapper = new QueryWrapper<>();
        //构造菜单名称
        queryWrapper.like(!ObjectUtils.isEmpty(sysMenu.getLabel()), "label", sysMenu.getLabel());
        //排序
        queryWrapper.orderByAsc("order_num");
        //查询菜单列表
        List<SysMenu> menuList = baseMapper.selectList(queryWrapper);
        //生成菜单树
        List<SysMenu> menuTreeList = MenuTree.makeMenuTree(menuList, 0L);
        return menuTreeList;
    }

    /**
     * 查询上级菜单列表
     *
     * @return
     */
    @Override
    public List<SysMenu> getParentMenu() {
        QueryWrapper<SysMenu> queryWrapper = new QueryWrapper<>();
        //只查询type为目录和菜单的数据(type=0或type=1)
        queryWrapper.in("type", Arrays.asList(0, 1));
        //排序
        queryWrapper.orderByAsc("order_num");
        //查询菜单列表
        List<SysMenu> menuList = baseMapper.selectList(queryWrapper);
        //构造顶级菜单信息，如果数据库中的菜单表没有数据，选择上级菜单时则显示顶级菜单
        SysMenu sysMenu = new SysMenu();
        sysMenu.setMenuId(0L);
        sysMenu.setParentId(-1L);
        sysMenu.setLabel("顶级菜单");
        //将顶级菜单添加到集合
        menuList.add(sysMenu);
        //生成菜单树
        List<SysMenu> menuTreeList = MenuTree.makeMenuTree(menuList, -1L);
        return menuTreeList;
    }

    /**
     * 检查菜单下是否有子菜单
     *
     * @param menuId
     * @return
     */
    @Override
    public boolean hasChildrenOfMenu(Long menuId) {
        QueryWrapper<SysMenu> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("parent_id", menuId);
        Integer count = baseMapper.selectCount(queryWrapper);
        //如果数量大于0，表示存在
        if (count > 0) {
            return true;
        }
        return false;
    }

    /**
     * 查询分配权限树列表
     * <p>
     * 分析：
     * 分配权限前需要回显当前角色拥有的权限信息。被分配角色的权限信息，不能超出当前用户所拥有的权限信息。
     * 1. 查询当前登录用户的信息。
     * 2. 判断当前登录用户是否是管理员，如果是管理员，则查询所有的权限信息；如果不是管理员，则需要根据当前用户Id查询出当前用户所拥有的权限信息。
     * 3. 将当前登录用户所拥有的权限封装成菜单树。
     * 4. 查询要分配角色拥有的权限列表，进行数据回显。
     * 保存角色权限关系时，需要删除该角色原有的权限信息，再保存新的权限信息。
     *
     * @param userId
     * @param roleId
     * @return
     */
    @Override
    public RoleMenuVo getAssignMenuTree(Long userId, Long roleId) {
        //查询当前登录用户的信息
        SysUser sysUser = sysUserMapper.selectById(userId);
        List<SysMenu> menuList = null;
        //判断当前用户是否是管理员
        if (!ObjectUtils.isEmpty(sysUser.getIsAdmin()) && sysUser.getIsAdmin() == 1) {
            //是管理员，查询全部权限
            menuList = baseMapper.selectList(null);
        } else {
            //不是管理员，根据当前用户id查询自己所拥有的权限
            menuList = baseMapper.selectMenuPermsByUserId(userId);
        }
        //将当前登录用户所拥有的权限封装成菜单树
        List<SysMenu> sysMenuTreeList = MenuTree.makeMenuTree(menuList, 0L);
        //查询要分配角色拥有的权限列表
        List<SysMenu> roleMenuList = baseMapper.selectMenuPermsByRoleId(roleId);
        //找出该角色存在的数据
        List<Long> listIds = new ArrayList<Long>();
        Optional.ofNullable(menuList).orElse(new ArrayList<>())
                .stream()
                //等同于 obj -> obj!=null
                .filter(Objects::nonNull)
                .forEach(item -> {
                    Optional.ofNullable(roleMenuList).orElse(new ArrayList<>())
                            .stream()
                            .filter(Objects::nonNull)
                            .forEach(obj -> {
                                //判断两者的权限是否一致，如果一致，则表示拥有该权限
                                if (item.getMenuId().equals(obj.getMenuId())) {
                                    listIds.add(obj.getMenuId());
                                    return;
                                }
                            });
                });
        RoleMenuVo roleMenuVo = new RoleMenuVo();
        roleMenuVo.setMenuList(sysMenuTreeList);
        roleMenuVo.setCheckList(listIds.toArray());
        return roleMenuVo;
    }
}
